﻿using Audit.Core;
using Audit.WebApi;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.DependencyInjection;
using Serilog;
using Serilog.Events;
using Shared.Service.Logging.Serilog;

namespace Shared.Service.Logging.AuditNet
{
    public static class AuditExtension
    {
        private const string CorrelationIdField = "CorrelationId";

        public static void AddAuditBySerilog(this IServiceCollection services, string appName)
        {
            //output
            Audit.Core.Configuration.Setup()
                .UseSerilog(config => config
                    .LogLevel(ev => LogEventLevel.Warning)
                    .Logger(ev => Log.Logger),
                     appName)
                .WithCreationPolicy(EventCreationPolicy.InsertOnEnd)
                .ResetActions();

            services.Configure<KestrelServerOptions>(options =>
            {
                options.AllowSynchronousIO = true;
            });

            services.Configure<IISServerOptions>(options =>
            {
                options.AllowSynchronousIO = true;
            });
        }

        public static void UseAuditCorrelationId(this IApplicationBuilder app, IHttpContextAccessor ctxAccessor)
        {
            Audit.Core.Configuration.AddCustomAction(ActionType.OnScopeCreated, scope =>
            {
                var httpContext = ctxAccessor.HttpContext;
                scope.Event.CustomFields[CorrelationIdField] = httpContext.TraceIdentifier;
            });
        }

        public static void UseAuditBySerilog(this IApplicationBuilder app)
        {
            //compatibility IncludeRequestBody 
            app.Use(async (context, next) =>
            {
                context.Request.EnableBuffering();
                await next();
            });

            //controller
            app.UseAuditMiddleware(config => config
                .FilterByRequest(rq => !rq.Path.Value.ToLower().EndsWith("/health"))
                .FilterByRequest(rq => !rq.Path.Value.ToLower().EndsWith("/metrics"))
                .IncludeHeaders()
                .IncludeRequestBody()
                .IncludeResponseHeaders()
                .IncludeResponseBody()
                .WithEventType("{verb}.{url}")
            );
        }
    }
}
